本篇是故事五的「踩雷」篇。
本篇要回答:一個看似合理的介面需求——「回傳指令是否成功」——為什麼在非同步架構裡是一道無解題?
系統採用非同步發布/訂閱(Publish/Subscribe)通訊,一道遠端控制指令的完整旅程長這樣:
呼叫端提出控制要求
↓
Publisher 發布命令
↓
訊息系統或 Broker 接收
↓
Subscriber 收到訊息
↓
應用程式解析與處理
↓
遠端設備接受或拒絕
↓
設備執行動作
↓
設備或系統回報最後結果
(去識別化說明:本故事依親身專案經驗重建,具體協定與元件名稱略去,以通用 Pub/Sub 描述;介面需求的原始說法以語意重述。)
然後介面需求來了,形狀非常樸素:
publish(command)
↓
success = True / False
呼叫端希望這個函式回傳時,就知道「指令成功了沒」。八層旅程,被要求壓縮成一個當場交卷的布林值。
第一時間我甚至覺得這個要求很合理——同步 API 不都這樣寫嗎?呼叫、回傳、成功失敗一翻兩瞪眼。卡住之後才意識到問題:publish() 返回的那一刻,指令可能才剛進 Broker 的佇列,Subscriber 還沒收到、設備還沒表態、動作更沒發生。此刻的 Publisher 手上唯一的真話是「我送出去了」,但介面逼它回答的是「事情辦成了嗎」。
要求最前面那一層替最後面的結果作保,等於要求快遞員在收件當下簽署「對方一定會喜歡這份禮物」。
第一步不是設計方案,是把「成功」這個詞拆開。對方口中的成功,可能是以下任何一層:Publisher 接受呼叫、訊息成功發布、Broker 收到、Subscriber 收到、應用程式開始處理、設備接受命令、設備完成動作、外部狀態符合要求。八個候選語意,介面上只有一個 success 欄位——需求方與實作方各自心裡想的是哪一層,從來沒有對齊過。
區分證據等級。已確認事實:Pub/Sub 架構下 Publisher 在發布當下不持有遠端執行結果,這是架構性質,不是實作缺陷。合理推論:需求方要的其實是「外部效果完成」那一層。尚未對齊(當時):成功的定義本身。
本篇結論:
指令才剛離開 Publisher,我們卻已經要求它替遠端設備簽下完工證明。
下一篇(Day 22)把每一層能提供的「收據」攤開:送出、送達、受理、執行與完成,到底哪一個叫成功?